#include "pt100.h"
#include <math.h>
#include "hem_port.h"
#include "lib.h"
#include "main.h"
#define R0 100.0f
#define A  3.9083e-3
#define B  -5.775e-7
#define C  -4.183e-12

float uf_res[3] = {0.0f};//0-IN15，1-IN16，2-IN17
float uf_res_average[3] = {0.0f};

/**
 * @brief 通过pt100电阻值计算温度
 * @param  resistance 测量的电阻值(Ω)
 * @return 温度值(℃)
 */
double pt100_resistance_to_temperature(double resistance)
{
    double temp = 0.0;
    double discriminant = 0.0;

    /*检查电阻值是否再有效范围内*/
    if((resistance < 18.52) || (resistance > 390.48))
    {
        return temp;
    }

    if(resistance >= R0)/*正温度区域*/
    {
        /*解二次方程：R  = R0 *(1+A*T+B*T*T)*/
        discriminant = A * A - 4 * B * (1 - resistance/R0);
        if(discriminant >= 0){
            temp = (-A + sqrt(discriminant)) / (2 * B);
        }else{
            return -999.0;
        }
    }
    else {/*负温度区域*/
        double T = -100.0;
        double pre_diff = 100.0;
        for(int i = 0; i < 100; i++)/*最多迭代100次*/
        {
            double R_calc = R0 * (1.0 + A*T + B*T*T + C*(T-100.0)*T*T*T);
            double diff = resistance - R_calc;

            if(fabs(diff) < 0.001) break;
            if(fabs(diff) >= pre_diff){
                break;
            }
            pre_diff = fabs(diff);
            /*更新温度估计值*/
            double dRdT = R0*(A+2*B*T + C*(4*T*T - 300*T*T));
            T += 0.5 * diff / dRdT;
        }
        temp = T;
    }
    return temp;
}

#define MIN_TEMP -40
#define MAX_TEMP 219
#define TEMP_STEP 1
#define TABLE_SIZE ((MAX_TEMP - MIN_TEMP) / TEMP_STEP + 1)
/*PT100分度表(电阻值数组)*/
static double ud_pt100_table[TABLE_SIZE] = {
    84.28, 84.67, 85.07, 85.46, 85.86, 86.25, 86.65, 87.04, 87.44, 87.83,/*-40℃~-31℃*/
    88.22, 88.62, 89.01, 89.41, 89.80, 90.19, 90.59, 90.98, 91.37, 91.77,/*-30℃~-21℃*/
    92.16, 92.55, 92.95, 93.34, 93.73, 94.12, 94.52, 94.91, 95.30, 95.69,/*-20℃~-11℃*/
    96.09, 96.48, 96.87, 97.26, 97.65, 98.04, 98.44, 98.83, 99.22, 99.61,/*-10℃~-1℃*/
    100.00,100.39,100.78,101.17,101.56,101.95,102.34,102.73,103.12,103.51,/*0℃~9℃*/
    103.90,104.29,104.68,105.07,105.46,105.85,106.24,106.63,107.02,107.41,/*10℃~19℃*/
    107.79,108.18,108.57,108.96,109.35,109.73,110.12,110.51,110.90,111.29,/*20℃~29℃*/
    111.67,112.06,112.45,112.83,113.22,113.61,114.00,114.38,114.77,115.15,/*30℃~39℃*/
    115.54,115.93,116.31,116.70,117.08,117.47,117.86,118.24,118.63,119.01,/*40℃~49℃*/
    119.40,119.78,120.17,120.55,120.94,121.32,121.71,122.09,122.47,122.86,/*50℃~59℃*/
    123.24,123.63,124.01,124.39,124.78,125.16,125.54,125.93,126.31,126.69,/*60℃~69℃*/
    127.08,127.46,127.84,128.22,128.61,128.99,129.37,129.75,130.13,130.52,/*70℃~79℃*/
    130.88,131.26,131.64,132.02,132.39,132.77,133.15,133.53,133.91,134.29,/*80℃~89℃*/
    134.71,135.09,135.47,135.85,136.23,136.61,136.99,137.37,137.75,138.13,/*90℃~99℃*/
    138.51,138.88,139.26,139.64,140.02,140.40,140.78,141.16,141.54,141.91,/*100℃~109℃*/
    142.27,142.65,143.03,143.41,143.79,144.17,144.55,144.93,145.31,145.69,/*110℃~119℃*/
    146.07,146.44,146.82,147.20,147.57,147.95,148.33,148.70,149.08,149.46,/*120℃~129℃*/
    149.83,150.21,150.58,150.96,151.33,151.71,152.08,152.46,152.83,153.21,/*130℃~139℃*/
    153.58,159.96,154.33,154.71,155.08,155.46,156.83,156.20,156.58,156.95,/*140℃~149℃*/
    157.33,157.70,158.07,158.45,158.82,159.19,159.56,159.94,160.31,160.68,/*150℃~159℃*/
    161.05,161.43,161.80,162.17,162.54,162.91,163.29,163.66,164.03,164.40,/*160℃~169℃*/
    164.77,165.14,165.51,165.89,166.26,166.63,167.00,167.37,167.74,168.11,/*170℃~179℃*/
    168.48,168.85,169.22,169.59,169.96,170.33,170.70,171.07,171.43,171.80,/*180℃~189℃*/
    172.17,172.54,172.91,173.28,173.65,174.02,174.38,174.75,175.12,175.49,/*190℃~199℃*/
    175.86,176.22,176.59,176.96,177.33,177.69,178.06,178.43,178.79,179.16,/*200℃~209℃*/
    179.53,179.89,180.26,180.63,180.99,181.36,181.72,182.09,182.46,182.82,/*210℃~219℃*/
};
/**
 * @brief 使用二分查找在PT100分度表中定位电阻位置
 * @param resistance 测量的电阻值(Ω)
 * @return 温度值(°C)
 */
double pt100_lookup_temperature(double resistance)
{
    if(resistance < ud_pt100_table[0]) return (MIN_TEMP - 10.0);
    if(resistance > ud_pt100_table[TABLE_SIZE - 1]) return (MAX_TEMP + 10.0);
    // 二分查找定位电阻值在表中的位置
    uint16_t low = 0;
    uint16_t high = TABLE_SIZE - 1;
    uint16_t mid = 0;
    while(low <= high)
    {
        mid = (low + high) / 2;
        if(resistance > ud_pt100_table[mid]) {
            low = mid + 1;
        } else if(resistance < ud_pt100_table[mid]) {
            high = mid - 1;
        } else {
            return (mid * TEMP_STEP + MIN_TEMP);// 找到精确匹配
        }
    }
    // 此时 low > high，电阻值在 high 和 low 索引之间
    // 线性插值计算温度
    uint16_t lower_index = (ud_pt100_table[high] < resistance) ? high : low - 1;
    uint16_t upper_index = lower_index + 1;
    
    double t_R0 = ud_pt100_table[lower_index];
    double t_R1 = ud_pt100_table[upper_index];
    double t_T0 = MIN_TEMP + lower_index * TEMP_STEP;
    
    // 线性插值公式: T = T0 + (R - R0) * (T1 - T0) / (R1 - R0)
    double temperature = t_T0 + (resistance - t_R0) * TEMP_STEP / (t_R1 - t_R0);
    
    return temperature;
}

double ud_temperature      = 0;
double ud_temperature_else = 0;

void pt100_test(void)
{
    uint8_t index = 0;
    for(index = 0; index < 3;index++){
        uf_res_average[index] = Lib_moving_average_filter(index,uf_res[index]);
		if(uf_res_average[index] > 65535.0f) uf_res_average[index] = 65535.0f;
    }
    ud_temperature = pt100_resistance_to_temperature((double)uf_res_average[1]/100);
    ud_temperature_else = pt100_lookup_temperature((double)uf_res_average[1]/100);
}
void pt100_tick(uint32_t tick)
{
    if(tick % TIME_OUT_10MS == 0) {
	    pt100_test();
    }
}
